import fs from 'fs';
import path from 'path';
import { QueryTypes } from 'sequelize';
import sequelize from '@/config/database';
import { getLogger } from "@/utils/logger";

// 创建数据库初始化专用的日志记录器
const logger = getLogger("db-init", {
	console: false,
});

const consoleLogger = getLogger("db-init");

// 导入 SQL 初始化文件路径
const SQL_INIT_FILE = path.resolve(process.cwd(), process.env.SQL_INIT_PATH || 'sql/init.sql');

/**
 * SQL语句类型接口
 */
interface SqlStatement {
  type: 'CREATE' | 'INSERT' | 'DELETE' | 'UPDATE' | 'OTHER';
  tableName: string;
  sql: string;
  executionOrder: number; // 执行顺序优先级
}

/**
 * 表信息映射接口
 */
interface TableInfo {
  createSql?: string;
  dataSqls: Array<{sql: string, type: string, executionOrder: number}>;
}

/**
 * 读取SQL文件内容
 * @param sqlFilePath SQL文件路径
 * @returns SQL文件内容
 */
function readSqlFile(sqlFilePath: string): string {
  try {
    const fullPath = path.resolve(sqlFilePath);
    logger.info(`读取SQL文件: ${fullPath}`);
    return fs.readFileSync(fullPath, 'utf8');
  } catch (error) {
    consoleLogger.error(`读取SQL文件失败: ${error instanceof Error ? error.message : String(error)}`);
    throw new Error(`读取SQL文件失败: ${error instanceof Error ? error.message : String(error)}`);
  }
}

/**
 * 解析SQL文件内容，提取建表语句和数据操作语句
 * @param sqlContent SQL文件内容
 * @returns 表名与对应的创建语句和数据操作语句的映射
 */
function parseSqlFile(sqlContent: string): Map<string, TableInfo> {
  consoleLogger.info('开始解析SQL文件...');
  
  // 移除单行注释
  let contentWithoutComments = sqlContent.replace(/--.*$/gm, '');
  
  // 替换sysdate()函数为NOW()
  contentWithoutComments = contentWithoutComments.replace(/sysdate\(\)/gi, 'NOW()');
  
  // 分割SQL语句，处理引号和分号
  const statements: string[] = [];
  let currentStatement = '';
  let inString = false;
  let stringChar = '';
  
  for (let i = 0; i < contentWithoutComments.length; i++) {
    const char = contentWithoutComments[i];
    
    // 处理字符串
    if ((char === "'" || char === '"') && contentWithoutComments[i - 1] !== '\\') {
      if (!inString) {
        inString = true;
        stringChar = char;
      } else if (char === stringChar) {
        inString = false;
      }
    }
    
    // 添加当前字符到语句
    currentStatement += char;
    
    // 处理语句分隔符
    if (char === ';' && !inString) {
      statements.push(currentStatement.trim());
      currentStatement = '';
    }
  }
  
  // 添加最后一个语句（如果没有以分号结束）
  if (currentStatement.trim()) {
    statements.push(currentStatement.trim());
  }

  // 将语句分为CREATE和数据操作语句
  const sqlStatements: SqlStatement[] = statements
    .filter(stmt => stmt.length > 0)
    .map(stmt => {
      const upperStmt = stmt.toUpperCase().trim();
      let type: 'CREATE' | 'INSERT' | 'DELETE' | 'UPDATE' | 'OTHER' = 'OTHER';
      let tableName = '';
      let executionOrder = 50; // 默认执行优先级
      
      if (upperStmt.startsWith('CREATE TABLE')) {
        // 提取表名，考虑可能有的反引号
        const tableNameMatch = stmt.match(/CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?(?:`|")?([a-zA-Z0-9_]+)(?:`|")?/i);
        tableName = tableNameMatch ? tableNameMatch[1] : '';
        type = 'CREATE';
        executionOrder = 10; // 创建表优先级最高
      } else if (upperStmt.startsWith('INSERT INTO')) {
        // 提取表名，考虑可能有的反引号
        const tableNameMatch = stmt.match(/INSERT\s+INTO\s+(?:`|")?([a-zA-Z0-9_]+)(?:`|")?/i);
        tableName = tableNameMatch ? tableNameMatch[1] : '';
        type = 'INSERT';
        
        // 给包含SELECT子查询的INSERT语句较低优先级
        if (upperStmt.includes('SELECT')) {
          executionOrder = 40; // 包含子查询的插入优先级较低
        } else {
          executionOrder = 20; // 普通插入语句优先级较高
        }
      } else if (upperStmt.startsWith('DELETE')) {
        // 提取表名，考虑可能有的反引号
        const tableNameMatch = stmt.match(/DELETE\s+FROM\s+(?:`|")?([a-zA-Z0-9_]+)(?:`|")?/i);
        tableName = tableNameMatch ? tableNameMatch[1] : '';
        type = 'DELETE';
        executionOrder = 30; // 删除操作优先级中等
      } else if (upperStmt.startsWith('UPDATE')) {
        // 提取表名，考虑可能有的反引号
        const tableNameMatch = stmt.match(/UPDATE\s+(?:`|")?([a-zA-Z0-9_]+)(?:`|")?/i);
        tableName = tableNameMatch ? tableNameMatch[1] : '';
        type = 'UPDATE';
        executionOrder = 35; // 更新操作优先级中等
      } else if (upperStmt.startsWith('DROP TABLE')) {
        // 提取表名，考虑可能有的IF EXISTS和反引号
        const tableNameMatch = stmt.match(/DROP\s+TABLE\s+(?:IF\s+EXISTS\s+)?(?:`|")?([a-zA-Z0-9_]+)(?:`|")?/i);
        tableName = tableNameMatch ? tableNameMatch[1] : '';
        // DROP语句我们不直接执行，仍标记为OTHER
        executionOrder = 5; // 删表操作优先级最高
      }
      
      return {
        type,
        tableName,
        sql: stmt,
        executionOrder
      };
    });

  // 创建表信息映射
  const tableInfoMap = new Map<string, TableInfo>();
  
  // 处理CREATE语句
  sqlStatements
    .filter(stmt => stmt.type === 'CREATE' && stmt.tableName)
    .forEach(stmt => {
      tableInfoMap.set(stmt.tableName, { 
        createSql: stmt.sql, 
        dataSqls: [] 
      });
    });

  // 处理数据操作语句
  sqlStatements
    .filter(stmt => ['INSERT', 'DELETE', 'UPDATE'].includes(stmt.type) && stmt.tableName)
    .forEach(stmt => {
      const tableInfo = tableInfoMap.get(stmt.tableName);
      if (tableInfo) {
        tableInfo.dataSqls.push({
          sql: stmt.sql,
          type: stmt.type,
          executionOrder: stmt.executionOrder
        });
      } else {
        // 如果没有创建语句，也创建一个条目来保存数据操作语句
        tableInfoMap.set(stmt.tableName, { 
          dataSqls: [{
            sql: stmt.sql,
            type: stmt.type,
            executionOrder: stmt.executionOrder
          }]
        });
      }
    });

  logger.info(`SQL文件解析完成，共解析出 ${tableInfoMap.size} 个表的信息`);
  return tableInfoMap;
}

/**
 * 检查表是否存在
 * @param tableName 表名
 * @returns 表是否存在
 */
async function checkTableExists(tableName: string): Promise<boolean> {
  const database = sequelize.getDatabaseName();
  const query = `
    SELECT COUNT(*) as count 
    FROM information_schema.tables 
    WHERE table_schema = ? AND table_name = ?
  `;
  
  try {
    const result = await sequelize.query(query, {
      replacements: [database, tableName],
      type: QueryTypes.SELECT,
      plain: true
    }) as { count: number };
    
    return result.count > 0;
  } catch (error) {
    consoleLogger.error(`检查表 ${tableName} 是否存在时出错: ${error instanceof Error ? error.message : String(error)}`);
    throw error;
  }
}

/**
 * 创建表
 * @param tableName 表名
 * @param createSql 创建表的SQL语句
 */
async function createTable(tableName: string, createSql: string): Promise<void> {
  try {
    consoleLogger.info(`开始创建表: ${tableName}`);
    // 首先尝试删除表（如果存在）
    try {
      await sequelize.query(`DROP TABLE IF EXISTS ${tableName}`, { type: QueryTypes.RAW });
    } catch (dropError) {
      consoleLogger.warn(`删除表 ${tableName} 失败（可能不存在）: ${dropError instanceof Error ? dropError.message : String(dropError)}`);
      // 继续创建表流程，不抛出异常
    }
    
    // 创建表
    await sequelize.query(createSql, { type: QueryTypes.RAW });
    consoleLogger.info(`表 ${tableName} 创建成功`);
  } catch (error) {
    consoleLogger.error(`创建表 ${tableName} 失败: ${error instanceof Error ? error.message : String(error)}`);
    throw error;
  }
}

/**
 * 检查表是否有数据
 * @param tableName 表名
 * @returns 是否有数据
 */
async function checkTableHasData(tableName: string): Promise<boolean> {
  try {
    const query = `SELECT COUNT(*) as count FROM ${tableName}`;
    const result = await sequelize.query(query, {
      type: QueryTypes.SELECT,
      plain: true
    }) as { count: number };
    
    return result.count > 0;
  } catch (error) {
    consoleLogger.error(`检查表 ${tableName} 是否有数据时出错: ${error instanceof Error ? error.message : String(error)}`);
    throw error;
  }
}

/**
 * 执行数据操作语句
 * @param tableName 表名
 * @param dataSqls 数据操作SQL语句列表
 */
async function executeDataSqls(tableName: string, dataSqls: Array<{sql: string, type: string, executionOrder: number}>): Promise<void> {
  try {
    consoleLogger.info(`开始执行表 ${tableName} 的数据操作`);
    
    // 按优先级排序SQL语句
    const sortedSqls = [...dataSqls].sort((a, b) => a.executionOrder - b.executionOrder);
    
    for (const {sql, type} of sortedSqls) {
      consoleLogger.info(`执行${type}语句: ${sql.substring(0, 100)}...`);
      await sequelize.query(sql, { type: QueryTypes.RAW });
    }
    
    consoleLogger.info(`表 ${tableName} 数据操作完成`);
  } catch (error) {
    consoleLogger.error(`执行表 ${tableName} 数据操作失败: ${error instanceof Error ? error.message : String(error)}`);
    throw error;
  }
}

/**
 * 初始化数据库表和数据
 * @param sqlFilePath SQL文件路径，默认使用项目中的 sql_init.sql 文件
 */
export async function initDatabase(sqlFilePath: string = SQL_INIT_FILE): Promise<void> {
  try {
    consoleLogger.info('开始数据库初始化...');
    
    // 读取SQL文件
    const sqlContent = readSqlFile(sqlFilePath);
    
    // 解析SQL文件
    const tableInfoMap = parseSqlFile(sqlContent);
    
    // 统计初始化结果
    const stats = {
      tablesChecked: 0,
      tablesCreated: 0,
      tablesWithDataInit: 0,
      errors: 0
    };
    
    // 先处理表创建
    for (const [tableName, tableInfo] of tableInfoMap.entries()) {
      try {
        stats.tablesChecked++;
        
        // 检查并创建表
        const tableExists = await checkTableExists(tableName);
        if (!tableExists) {
          if (tableInfo.createSql) {
            await createTable(tableName, tableInfo.createSql);
            stats.tablesCreated++;
            consoleLogger.info(`表 ${tableName} 已创建`);
          } else {
            consoleLogger.warn(`表 ${tableName} 不存在，但没有找到创建语句，跳过`);
            // 如果需要的表不存在且没有创建语句，记为错误
            stats.errors++;
          }
        } else {
          logger.info(`表 ${tableName} 已存在，跳过创建步骤`);
        }
      } catch (error) {
        stats.errors++;
        consoleLogger.error(`处理表 ${tableName} 时出错: ${error instanceof Error ? error.message : String(error)}`);
        // 继续处理其他表
      }
    }
    
    // 再处理数据操作，确保所有表都已创建
    for (const [tableName, tableInfo] of tableInfoMap.entries()) {
      try {
        // 检查表是否存在（可能是由其他地方创建的）
        const tableExists = await checkTableExists(tableName);
        
        if (tableExists) {
          // 只有当表有数据操作SQL时才执行
          if (tableInfo.dataSqls.length > 0) {
            // 检查是否为仅包含INSERT语句的表
            const onlyInserts = tableInfo.dataSqls.every(sql => sql.type === 'INSERT');
            
            // 对于仅包含INSERT语句的表，检查是否已有数据
            let shouldExecute = true;
            if (onlyInserts) {
              const hasData = await checkTableHasData(tableName);
              if (hasData) {
                logger.info(`表 ${tableName} 已有数据，跳过数据初始化`);
                shouldExecute = false;
              }
            }
            
            // 执行数据操作
            if (shouldExecute) {
              await executeDataSqls(tableName, tableInfo.dataSqls);
              stats.tablesWithDataInit++;
              consoleLogger.info(`表 ${tableName} 数据已初始化`);
            }
          } else {
            logger.info(`表 ${tableName} 没有定义数据操作，跳过数据初始化`);
          }
        } else {
          consoleLogger.warn(`表 ${tableName} 不存在，无法执行数据操作`);
          stats.errors++;
        }
      } catch (error) {
        stats.errors++;
        consoleLogger.error(`执行表 ${tableName} 数据操作时出错: ${error instanceof Error ? error.message : String(error)}`);
        // 继续处理其他表
      }
    }
    
    // 输出统计信息
    // consoleLogger.info('数据库初始化完成，统计信息:');
    // consoleLogger.info(`检查的表: ${stats.tablesChecked}`);
    // consoleLogger.info(`创建的表: ${stats.tablesCreated}`);
    // consoleLogger.info(`执行数据操作的表: ${stats.tablesWithDataInit}`);
    // consoleLogger.info(`错误数: ${stats.errors}`);
    
    if (stats.errors > 0) {
      consoleLogger.warn('初始化过程中出现错误，请检查日志');
    } else {
      consoleLogger.info('数据库初始化成功完成');
    }
    
  } catch (error) {
    consoleLogger.error(`数据库初始化失败: ${error instanceof Error ? error.message : String(error)}`);
    throw error;
  }
}

export default initDatabase;
